home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-02-09 | 8.5 KB | 253 lines | [TEXT/PJMM] |
- { This Code Resource handles a CDEF that is stored as a driver resource }
- { Our driver resource will actually be type 'DRVR', ID = 500. }
- { NOTE: The DATA resource also compiled with the driver resource must have its ID changed }
- { to -32 }
- unit CDEFCode;
-
- interface
-
- function Main (VarCode: Integer; TheControl: ControlHandle; message: integer; Param: Longint): Longint;
-
- implementation
-
- const
- { these are the byte offsets into the driver header for the jmp offset table }
- drvrSelOpenOffset = 2; { in hiword of LongArrHdl^^[2] }
- drvrSelCloseOffset = 4; { in hiword of LongArrHdl^^[4] }
- drvrSelControlOffset = 3; { in hiword of LongArrHdl^^[3] }
-
- drvrResType = 'DRVR';
- drvrResID = 500;
- dataInternalID = 0; { your DATA resource must have a resource ID of -(dataInternalID + 1) * 32 }
-
- type
- { this array typecasts the driver to access its offset table. }
- { Because Think Pascal has no word type, we can extra the low or high word of LongInts }
- { using the Loword and Hiword routines }
- LongArr = array[0..10] of LongInt;
- LongArrPtr = ^LongArr;
- LongArrHdl = ^LongArrPtr;
-
- function CallDriver (devCtlEnt: DCtlPtr; paramBlock: ParmBlkPtr; theDriverOfs: Ptr): integer;
- inline
- $2F0A, { MOVEA.L A2,-(A7) ; preserve A2 in the function return }
- $246F, $0004, { MOVEA.L 4(A7),A2 ; Routine to jump to }
- $206F, $0008, { MOVEA.L $8(A7), A0 ; parmBlkPtr must go in A0 }
- $226F, $000C, { MOVEA.L $C(A7), A1 ; dCtlPtr must go in A1 }
- $4E92, { JSR (A2) ; call the driver - D0 will contain the result }
- $245F, { MOVEA.L (A7)+,A2 ; restore A2 before setting return value }
- $DEFC, $000C, { ADDA.W #$C, A7 ; restore the stack except for function return value }
- $3E80; { MOVEA.L D0, (A7) ; return value on stack }
-
- {---------------------------------------------------------------}
-
- function Main (VarCode: Integer; TheControl: ControlHandle; message: integer; Param: Longint): Longint;
-
- type
- { CodeToDriver passes parameters from the code resource into driver }
- { add or change any parameters that apply to your code resource }
- CodeToDriver = record
- fMessage: integer; { message }
- fVarCode: integer; { VarCode }
- fControl: ControlHandle; { theControl }
- fParam: LongInt; { Param }
- fResult: LongInt; { result to return to Control Manager }
- end;
- CtoDPtr = ^CodeToDriver;
- CtoDHdl = ^CtoDPtr;
-
- {******************************************}
-
- procedure InitRtn;
- { 1. Allocate and initialize dCtlEntry and store it in theControl^^.contrlData }
- { 2. Load the driver and store it in dCtlEntry.dCtlDriver }
- { 2. Call the driver with the Open message }
- var
- theDCEHdl: DCtlHandle;
- theDriver: Handle;
- theCtoDHdl: CtoDHdl;
- theOSErr: OSErr;
- dummyIOPB: ParamBlockRec; { used as a dummy field }
- driverOfs: Ptr;
- name: Str255;
- begin
- { allocate the Driver Control Entry }
- theDCEHdl := DCtlHandle(NewHandle(sizeof(DCtlEntry)));
- {** memory error handling here **}
- MoveHHi(handle(theDCEHdl));
- HLock(handle(theDCEHdl));
-
- { allocate CodeToDriver and set it up. }
- { Fields fVarCode and fControl only need to be set once }
- theCtoDHdl := CtoDHdl(NewHandle(sizeof(CodeToDriver)));
- {** memory error handling here **}
- MoveHHi(handle(theCtoDHdl));
- HLock(handle(theCtoDHdl));
- with theCtoDHdl^^ do
- begin
- fMessage := initCntl;
- fVarCode := varCode;
- fControl := theControl;
- fParam := param;
- end; { with theCtoDHdl^^ }
-
- { load the driver }
- theDriver := GetResource(drvrResType, drvrResID);
- {** memory error handling here **}
- MoveHHi(theDriver);
- HLock(theDriver);
- HNoPurge(theDriver);
-
- { fill in the Driver Control Entry and store it in the control }
- with theDCEHdl^^ do
- begin
- dCtlDriver := Ptr(theDriver);
- dCtlFlags := $4400; { allow Control }
- dCtlQHdr.qFlags := 0; { not used }
- dCtlQHdr.qHead := nil; { not used }
- dCtlQHdr.qTail := nil; { not used }
- dCtlPosition := ord4(theCtoDHdl); { passing parameter block }
- dCtlStorage := nil; { for Think Pascal to set it up during Open }
- dCtlRefNum := dataInternalID; { Think will calculate an ID of -32 for its DATA resource }
- dCtlCurTicks := 0; { not used }
- dCtlWindow := nil; { not used }
- dCtlDelay := 0; { not used }
- dCtlEMask := 0; { not used }
- dCtlMenu := 0; { not used }
- end; { with theDCEHdl^^ }
- theControl^^.contrlData := handle(theDCEHdl);
-
- { now call the driver with the Open selector. dummyIOPB is a dummy field }
- { theDCEHdl and theDriver are already locked }
- driverOfs := Ptr(ord4(theDriver^) + hiword(LongArrHdl(theDriver)^^[drvrSelOpenOffset]));
-
- { Although we fill in some of dummyIOPB, the Think Pascal 2.0 }
- { driver structure doesn't use it }
- with dummyIOPB do
- begin
- qLink := nil;
- qType := Ord(ioQType);
- ioCmdAddr := driverOfs;
- ioTrap := 0;
- ioCompletion := nil;
- Name := '.Driver Name';
- ioNamePtr := @Name;
- ioRefNum := drvrResID + 1; { driver refNum + 1 }
- end; { with dummyIOPB }
- theOSErr := CallDriver(theDCEHdl^, @dummyIOPB, driverOfs);
- {** error handling here **}
- end; { InitRtn }
-
- {******************************************}
-
- procedure DisposeRtn;
- { 1. Call the Driver with the close message }
- { so it can unload its storage and segments }
- { 2. Dispose our own storage }
- var
- theDCEHdl: DCtlHandle;
- theDriver: Handle;
- theCtoDHdl: CtoDHdl;
- theOSErr: OSErr;
- dummyIOPB: ParamBlockRec; { used as a dummy field }
- driverOfs: Ptr;
-
- begin
- theDCEHdl := DCtlHandle(theControl^^.contrlData);
- theDriver := handle(theDCEHdl^^.dCtlDriver);
- LoadResource(theDriver); { in case it was purged after another code resource using it was disposed }
- HNoPurge(theDriver);
- HLock(theDriver); { in case it was unlocked by Think }
- theCtoDHdl := CtoDHdl(theDCEHdl^^.dCtlPosition);
-
- { Call the driver with the Close selector. dummyIOPB is a dummy field }
- { theDCEHdl and theDriver are already locked }
- theCtoDHdl^^.fMessage := dispCntl; { not really used, but... }
- driverOfs := Ptr(ord4(theDriver^) + hiword(LongArrHdl(theDriver)^^[drvrSelCloseOffset]));
-
- { Although we fill in some of dummyIOPB, the Think Pascal 2.0 }
- { driver structure doesn't use it }
- with dummyIOPB do
- begin
- qLink := nil;
- qType := Ord(ioQType);
- ioCmdAddr := driverOfs;
- ioTrap := 0;
- ioCompletion := nil;
- ioRefNum := drvrResID + 1; { driver refNum + 1 }
- end; { with dummyIOPB }
- theOSErr := CallDriver(theDCEHdl^, @dummyIOPB, driverOfs);
-
- { now dispose structures }
- DisposHandle(handle(theCtoDhdl));
- DisposHandle(handle(theDCEHdl));
- { don't dispose the driver since we may be sharing it with many instances of this CDEF }
- { instead, mark it to be purged and always call LoadResource before using it elsewhere }
- HPurge(theDriver);
- end; { DisposeRtn }
-
- {******************************************}
-
- function OtherRtns: LongInt;
- { 1. setup message }
- { 2. call driver with Control command }
- { 3. return function value }
- var
- theDCEHdl: DCtlHandle;
- theDriver: Handle;
- theCtoDHdl: CtoDHdl;
- theOSErr: OSErr;
- dummyIOPB: ParamBlockRec; { used as a dummy field }
- driverOfs: Ptr;
-
- begin
- theDCEHdl := DCtlHandle(theControl^^.contrlData);
- theDriver := handle(theDCEHdl^^.dCtlDriver);
- LoadResource(theDriver); { in case it was purged after another code resource using it was disposed }
- HNoPurge(theDriver);
- HLock(theDriver); { in case it was unlocked by Think }
- theCtoDHdl := CtoDHdl(theDCEHdl^^.dCtlPosition);
-
- with theCtoDHdl^^ do
- begin
- fMessage := message;
- fParam := param;
- fResult := 0; { init }
- end; { with }
-
- { Call the driver with the Control selector. dummyIOPB is a dummy field }
- { theDCEHdl and theDriver are already locked }
- driverOfs := Ptr(ord4(theDriver^) + hiword(LongArrHdl(theDriver)^^[drvrSelControlOffset]));
-
- { Although we fill in some of dummyIOPB, the Think Pascal 2.0 }
- { driver structure doesn't use it }
- with dummyIOPB do
- begin
- qLink := nil;
- qType := Ord(ioQType);
- ioCmdAddr := driverOfs;
- ioTrap := 0;
- ioCompletion := nil;
- ioRefNum := drvrResID + 1; { driver refNum + 1 }
- end; { with dummyIOPB }
- theOSErr := CallDriver(theDCEHdl^, @dummyIOPB, driverOfs);
-
- OtherRtns := theCtoDHdl^^.fResult;
- end; { OtherRtns }
-
- {******************************************}
-
- begin
- Main := 0; { initialize function result }
- case Message of
- InitCntl:
- InitRtn;
- DispCntl:
- DisposeRtn;
- otherwise
- Main := OtherRtns;
- end; { CASE }
- end; { Main }
-
-
- end. { UNIT CDEFCode }